package com.lianlianche.arch.jetpack.base

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.map
import androidx.lifecycle.viewModelScope
import com.lianlianche.arch.jetpack.ktx.toMessage
import kotlinx.coroutines.launch

/**
 * <pre>
 *     @author : Mid
 *     e-mail  : boyce903301689@gmail.com
 *     time    : 2019/7/25
 *     desc    : 对ViewModel的基础封装
 *               1.提供拉取数据/提交数据时，通知界面加载过渡操作
 *               2.将异常提示信息通知界面
 *     version : 1.0
 * </pre>
 */
open class BaseViewModel: ViewModel() {

    val fetchStatus by lazy { MutableLiveData<FetchType>().apply { value = FetchType.DEFAULT } }

    private val fetchDecorProxy = MutableLiveData<FetchDecor>()
    private val exceptionProxy = MutableLiveData<String>()

    open val fetchDecor = fetchDecorProxy.map { it }
    open val exception = exceptionProxy.map { it }
    val submitDecor = MutableLiveData<SubmitDecor>()



    /**
     * 拉取数据的时候可以伴有界面过渡效果
     */
    protected fun fetchOf(block: suspend () -> Unit) = viewModelScope.launch {
        try {
            fetchDecorProxy.value = ShowOfFetch(fetchStatus())
            block()
            fetchDecorProxy.value = HideOfFetch(fetchStatus())
            resetFetchStatus()
        } catch (t: Throwable) {
            fetchDecorProxy.value = HideOfFetch(fetchStatus())
            resetFetchStatus()
            throwException(t.toMessage())
            t.printStackTrace()
        }

    }


    /**
     * 提交数据的时候伴有界面过渡效果
     */
    protected fun submitOf(block: suspend () -> Unit) = viewModelScope.launch {
        try {
            submitDecor.value = ShowOfSubmit()
            block()
            submitDecor.value = HideOfSubmit()
            resetFetchStatus()
        } catch (t: Throwable) {
            submitDecor.value = HideOfSubmit()
            resetFetchStatus()
            throwException(t.toMessage())
            t.printStackTrace()
        }
    }


    /**
     * 改变数据拉取状态
     */
    fun changeFetchStatus(fetchType: FetchType) {
        fetchStatus.value = fetchType
    }

    /**
     * 抛出异常
     */
    fun throwException(message: String) {
        exceptionProxy.value = message
    }


    /**
     * 重置拉取数据效果的状态，当界面刷新/加载更多状态后应当重置，避免造成影响
     */
    private fun resetFetchStatus() {
        fetchStatus.value = FetchType.DEFAULT
    }

    /**
     * 获取当前拉取数据效果的状态
     */
    private fun fetchStatus(): FetchType {
        return fetchStatus.value ?: FetchType.DEFAULT
    }
}